package models

import (
	"strings"

	"gitee.com/sansaniot/ssiot-core/httpmvc/model"
	"gitee.com/sansaniot/ssiot-core/logger"
	"gorm.io/gorm"

	"ssnotify/common/dto"
	cDto "ssnotify/common/dto"
	"ssnotify/common/enums/sendtargettype"
	"ssnotify/common/utils"
	"ssnotify/internal/notify/models/query"
)

type NotifyConfig struct {
	Id             string          `json:"id" gorm:"primaryKey;type:varchar(64)"`
	Name           string          `json:"name" gorm:"type:varchar(128);comment:通知名称"`
	Source         string          `json:"source" gorm:"type:varchar(10);comment:来源：1：告警  2：用户操作 3：系统任务"`
	Status         string          `json:"status" gorm:"type:varchar(10);comment:状态：生效或不生效"`
	DeptId         string          `json:"deptId" gorm:"type:varchar(64);comment:分组id"`
	TemplateId     string          `json:"templateId" gorm:"type:text;comment:模板id"`
	Type           string          `json:"type" gorm:"type:text;comment:通知类型"`
	SendTarget     string          `json:"sendTarget" gorm:"type:text;comment:通知方式、短信、应用内等"`
	SendTargetType string          `json:"sendTargetType" gorm:"type:varchar(10);comment:通知方式、短信、应用内等"`
	CreatorId      string          `json:"creatorId" gorm:"type:varchar(64);comment:创建人id"`
	Creator        string          `json:"creator" gorm:"type:varchar(128);comment:创建人"`
	CreateTime     *cDto.LocalTime `json:"createTime" gorm:"type:timestamptz(6);comment:创建时间"`
	UpdateTime     *cDto.LocalTime `json:"updateTime" gorm:"type:timestamptz(6);comment:更新时间"`
	AgencyId       string          `json:"agencyId" gorm:"type:varchar(64);comment:机构用户id"`

	model.Model
}

func (NotifyConfig) TableName() string {
	return "sys_notify_config"
}

func (e *NotifyConfig) Generate() *NotifyConfig {
	o := *e
	return &o
}

// 通知配置信息
func (e *NotifyConfig) FindNotifyConfig(req *query.NotifyConfigGetReq) (list []NotifyConfig, err error) {
	list = make([]NotifyConfig, 0)
	err = e.FindList(&list, dto.MakeCondition(req.GetNeedSearch()))
	return
}

func (e *NotifyConfig) FindNotifyConfigPageList(req *query.NotifyConfigGetReq) (err error, result interface{}) {
	list := make([]NotifyConfig, 0)
	var count int64
	if req.AgencyId != req.UserId {
		// 非租户查无数据
		if req.PageIndex > 0 && req.PageSize > 0 {
			result = &cDto.Page{
				Records:   list,
				Total:     count,
				PageSize:  req.GetPageSize(),
				PageIndex: req.GetPageIndex(),
				Pages:     (count + int64(req.GetPageSize()) - 1) / int64(req.GetPageSize()),
				Other:     nil,
			}
		} else {
			result = list
		}
		return
	}
	if req.PageIndex > 0 && req.PageSize > 0 {
		err = e.FindPage(&list, &count,
			cDto.MakeCondition(req.GetNeedSearch()),
			cDto.OrderDest("create_time", true, req.OrderBy),
			cDto.Paginate(req.GetPageSize(), req.GetPageIndex()),
		)
		result = &cDto.Page{
			Records:   list,
			Total:     count,
			PageSize:  req.GetPageSize(),
			PageIndex: req.GetPageIndex(),
			Pages:     (count + int64(req.GetPageSize()) - 1) / int64(req.GetPageSize()),
			Other:     nil,
		}
	} else {
		err = e.FindList(&list,
			cDto.MakeCondition(req.GetNeedSearch()),
			cDto.OrderDest("create_time", true, req.OrderBy),
		)
		result = list
	}
	return
}

// 查询通知配置对应的通知用户信息
func (e *NotifyConfig) FindNotifyUserList(notifyConfig NotifyConfig) (notifyUsers []NotifyUser) {
	notifyUsers = make([]NotifyUser, 0)
	//获取发送人的数据类型(分组 用户 职务)
	sendTargetType := notifyConfig.SendTargetType
	//获取发送人对应的值
	sendTarget := notifyConfig.SendTarget
	//判断是否存在
	if len(sendTargetType) == 0 || len(sendTarget) == 0 {
		//缺少发送人的类型
		logger.Errorf("当前通知配置缺少发送人类型配置 notifyConfig=[%+v]", notifyConfig)
		//空值结果
		return
	}
	if strings.EqualFold(sendtargettype.TargetTypeOfCustom.Get().Type, sendTargetType) {
		//自定义邮件/手机号
		sendTargetObj := utils.BytesToMap([]byte(sendTarget))
		for k, v := range sendTargetObj {
			vstr := strings.ReplaceAll(v.(string), " ", "")
			if len(vstr) == 0 {
				continue
			}
			for _, vv := range strings.Split(vstr, ";") {
				notifyUser := NotifyUser{
					UserId:   "custom",
					Username: "custom",
				}
				if k == "email" {
					notifyUser.Email = vv
				} else if k == "mobile" {
					notifyUser.Mobile = vv
				}
				notifyUsers = append(notifyUsers, notifyUser)
			}
		}
	} else {
		//查询参数
		queryMap := make(map[string][]string)
		splitStr := strings.Split(strings.ReplaceAll(sendTarget, " ", ""), ",")
		//不同的类型处理
		if strings.EqualFold(sendtargettype.TargetTypeOfDept.Get().Type, sendTargetType) {
			//分组用户查询
			queryMap["deptIds"] = splitStr
		} else if strings.EqualFold(sendtargettype.TargetTypeOfPosition.Get().Type, sendTargetType) {
			//职务用户查询
			queryMap["positionKeys"] = splitStr
		} else if strings.EqualFold(sendtargettype.TargetTypeOfUser.Get().Type, sendTargetType) {
			//指定用户id的用户查询
			queryMap["userIds"] = splitStr
		}
		//查询数据库
		var err error
		if err = listNotifyUser(e.Orm, queryMap, &notifyUsers); err != nil {
			logger.Error(err)
			return
		}
	}
	//返回结果
	return
}

// 通知配置对应的用户集合
func listNotifyUser(db *gorm.DB, queryMap map[string][]string, userList *[]NotifyUser) (err error) {
	sql := `
SELECT
	* 
FROM
	(
	SELECT DISTINCT
		u.ID AS user_id,
		u.username,
		u.email,
		u.mobile,
		u.position_key,
		ud.dept_id,
		ROW_NUMBER ( ) OVER ( PARTITION BY u.ID ) AS row_num 
	FROM
		sys_user u
		LEFT JOIN sys_user_dept_r ud
		LEFT JOIN sys_dept d ON ud.dept_id = d.ID ON u.ID = ud.user_id 
	WHERE
		u.status = '1'
		#deptIn
		#userIn
		#posIn
	) ttt 
WHERE
	ttt.row_num = 1
`
	//部门类型
	if deptIds, ok := queryMap["deptIds"]; ok {
		cond := " AND ud.dept_id IN ('" + strings.Join(deptIds, "','") + "') "
		sql = strings.ReplaceAll(sql, "#deptIn", cond)
	} else {
		sql = strings.ReplaceAll(sql, "#deptIn", "")
	}
	//用户集合
	if userIds, ok := queryMap["userIds"]; ok {
		cond := " AND u.ID IN ('" + strings.Join(userIds, "','") + "') "
		sql = strings.ReplaceAll(sql, "#userIn", cond)
	} else {
		sql = strings.ReplaceAll(sql, "#userIn", "")
	}
	//职务类型
	if positionKeys, ok := queryMap["positionKeys"]; ok {
		cond := " AND u.position_key IN ('" + strings.Join(positionKeys, "','") + "') "
		sql = strings.ReplaceAll(sql, "#posIn", cond)
	} else {
		sql = strings.ReplaceAll(sql, "#posIn", "")
	}
	err = db.Raw(sql).Scan(userList).Error
	return
}
